package org.wevil.thread;

import java.io.*;
import java.net.Socket;

/**
 * 姜智飞阀门监听线程
 *
 * @since 2022/3/7
 */
public class SocketThread extends Thread {

    /**
     * 套接字
     */
    final Socket socket;

    public SocketThread(Socket socket, String threadName) {
        super(threadName);
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            if (!this.isInterrupted()) {
                DataInputStream dis = new DataInputStream(socket.getInputStream());
                OutputStream os = socket.getOutputStream();
                byte[] bytes = new byte[256];
                // 接收数据
                int len;
                while ((len = dis.read(bytes)) != -1) {
                    // 打印输出
                    String content = new String(bytes, 0, len);
                    // 获取发送方ip
                    String address = socket.getInetAddress() + ":" + socket.getPort();
                    System.out.println(this.getName() + "-" + address + "-接收到的内容：" + content);
                    // 判断是否651协议报文
                    boolean check = Message651UP.check(content);
                    if(check){
                        // 解析报文
                        Message651UP message651UP = Message651UP.parse(content);
                        // 获取设备编号
                        String rtuCd = message651UP.getRtuAddress();
                        // 记录设备编号和对应的线程id
                        ThreadUtils.setRtuThreadMap(rtuCd, getId());
                        // 判断报文类型， 33:正式报文, 2F:心跳报文, 43:开度查询, 42:控制开度
                        String functionCode = message651UP.getFunctionCode();
                        switch (functionCode) {
                            case "33": // 正式报文
                                System.out.println(this.getName() + "-记录报文数据");
                                // 记录报文数据
                                break;
                            case "2F": // 2F:心跳报文
                                // SOH STX ETX
                                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
                                String heart = Message651DN.getHeart(message651UP);
                                System.out.println(this.getName() + "-心跳回复：" + heart);
                                bw.write(heart);
                                bw.flush();
                                break;
                            case "43": // 开度查询
                                // 记录开度
                                System.out.println(this.getName() + "-记录开度");
                                String open = message651UP.getContent().split(" ")[3];
                                System.out.printf("rtuCd:%s, 开度：%s\r\n", rtuCd, open);
                                break;
                            case "42": // 控制开度
                                // 控制开度返回结果，不处理
                                System.out.println(this.getName() + "-开度返回结果，不处理");
                                break;
                        }
                    }
                    else{ // 不是651协议报文，关闭线程
                        System.out.println(this.getName() + "-不是651协议报文，关闭线程");
                        break;
                    }
                }
                // 读取数据完毕，关闭链接
                System.out.println(this.getName() + "-关闭线程[" + this.getName() + "]");
                interruptAndClose();
            }
            interruptAndClose();
        } catch (IOException e) {
            System.out.println(this.getName() + "-关闭线程[" + this.getName() + "]");
        } finally {
            interruptAndClose();
        }
    }

    /**
     * 关闭socket并中断线程
     *
     * @author wanglei
     * @since 2020/12/15
     */
    public void interruptAndClose() {
        this.interrupt();
        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 设置开度
     * */
    public void setOpen(String rtuCd, Integer open)  {
        try {
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            String setOpen = Message651DN.setOpen(rtuCd, open);
            bw.write(setOpen);
            bw.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询开度
     * */
    public void queryOpen(String rtuCd) {
        try {
            if(!socket.isClosed()){
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
                String open = Message651DN.getOpen(rtuCd);
                bw.write(open);
                bw.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
